/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file t4t_api.h
 * @brief T4T操作API定义
 */
#ifndef _T4T_API_H_
#define _T4T_API_H_

#include "nci_feature.h"

#if IS_FEATURE_ON(NCI_FEATURE_RW_T4T) // TODO: || IS_FEATURE_ON(NCI_FEATURE_T4T_NFCEE)

#include "nci_transport.h"

#define T4T_VERSION_UNKNOWN 0x00
#define T4T_VERSION_1_0 0x10
#define T4T_VERSION_2_0 0x20
#define T4T_VERSION_3_0 0x30

#define T4T_CLA_DEFAULT 0x00
#define T4T_CLA_DESFIRE 0x90

#define T4T_INS_SELECT 0xA4
#define T4T_INS_READ_BINARY 0xB0
#define T4T_INS_READ_BINARY_ODO 0xB1
#define T4T_INS_UPDATE_BINARY 0xD6
#define T4T_INS_UPDATE_BINARY_ODO 0xD7
#define T4T_INS_GET_HW_VERSION 0x60
#define T4T_INS_CREATE_APP 0xCA
#define T4T_INS_SELECT_APP 0x5A
#define T4T_INS_CREATE_DATAFILE 0xCD
#define T4T_INS_DES_WRITE 0x3D
#define T4T_P1_SELECT_BY_FILE 0x00
#define T4T_P1_SELECT_BY_NAME 0x04

#define T4T_P2_FIRST_OR_ONLY_00 0x00
#define T4T_P2_FIRST_OR_ONLY_0C 0x0C

#define T4T_SW_LEN 2
#define T4T_SW_OK 0x9000
#define T4T_SW_DES_OK 0x9100
#define T4T_SW_NOT_FOUND 0x6A82
#define T4T_SW_WRONG_PARAMS 0x6B00
#define T4T_SW_WRONG_LENGTH 0x6700
#define T4T_SW_CLASS_NOT_SUPPORTED 0x6E00
#define T4T_SW_INSTR_NOT_SUPPORTED 0x6D00
#define T4T_SW_CMD_NOT_ALLOWED 0x6986
#define T4T_SW_DES_DUPLICATE_ERROR 0x91DE

#define T4T_FILE_ID_LEN 2
#define T4T_NDEF_AID_LEN 7
#define T4T_FILE_SIZE_LEN 2

#define T4T_CC_FILE_ID 0xE103
#define T4T_LE_CC_FILE_DEF_LEN 0x11

#define T4T_ODO_HEADER_2BYTES_LENGTH 8

#define T4T_BER_TLV_LENGTH_1_BYTE 0x01
#define T4T_BER_TLV_LENGTH_2_BYTE 0x02
#define T4T_BER_TLV_LENGTH_3_BYTE 0x03


/** @brief APDU指令结构体定义 */
typedef struct {
    uint8_t cla;
    uint8_t ins;
    uint8_t p1;
    uint8_t p2;
    uint16_t lc;
    const uint8_t *p_dat;
    bool le_present;
    uint16_t le;
    bool skip_verify_sw;
} tT4T_APDU;

typedef tNCI_STATUS(*tT4T_TRANSMIT)(tNCI_BUF *cmd, tNCI_BUF *rsp);

/** @brief T4T指令传输的目标 */
typedef struct {
    /** @brief 向T4T设备发送原生APDU指令的函数指针 */
    tT4T_TRANSMIT transmit;
    /** @brief 当前选中的文件ID */
    uint16_t curr_selected_file_id;
    /** @brief 最后一条响应数据的状态字 */
    uint16_t last_sw;
} tT4T_TARGET;

/**
 * @brief 重置T4T目标的状态
 *
 * @note 不会重置transmit函数
 *
 * @param[in] target 需要重置的目标
 *
 * @return 重置成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_reset(tT4T_TARGET *target);
/**
 * @brief 发送原始APDU指令
 *
 * @param[in] target 指令发送的目标
 * @param[in] p_apdu 需要发送的APDU指令
 * @param[out] pp_rsp 响应数据
 *
 * @return 发送指令成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_send_apdu(tT4T_TARGET *target, tT4T_APDU *p_apdu, tNCI_BUF **pp_rsp);
/**
 * @brief 选择应用
 *
 * @param[in] target 指令发送的目标
 * @param[in] p_aid 应用ID
 * @param[in] aid_len 应用ID长度
 * @param[out] pp_rsp 响应数据
 *
 * @return 选择应用成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_select_application(tT4T_TARGET *target, const uint8_t *p_aid, uint16_t aid_len, tNCI_BUF **pp_rsp);
/**
 * @brief 选择文件
 *
 * @param[in] target 指令发送的目标
 * @param[in] file_id 需要选择的文件ID
 * @param[in] p2 P2参数, 可选：T4T_P2_FIRST_OR_ONLY_00, T4T_P2_FIRST_OR_ONLY_0C
 * @param[out] pp_rsp 响应数据
 * @return 选择文件成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_select_file(tT4T_TARGET *target, uint16_t file_id, uint8_t p2, tNCI_BUF **pp_rsp);
/**
 * @brief 读取文件
 *
 * @param[in] target 指令发送的目标
 * @param[in] offset 读取的起始偏移位置
 * @param[in] read_len 读取的长度
 * @param[in] check_len 是否校验读取到的数据长度
 * @param[out] pp_rsp 响应数据
 *
 * @return 读取文件成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_read_binary(tT4T_TARGET *target, uint16_t offset, uint16_t read_len, bool check_len, tNCI_BUF **pp_rsp);
/**
 * @brief 读取文件，Offset Data Object Feature
 *
 * @param[in] target 指令发送的目标
 * @param[in] offset 读取的起始偏移位置
 * @param[in] max_le 最大一条指令读取数据的长度
 * @param[out] pp_rsp 响应数据
 * @param[out] p_rsp_offset 返回pp_rsp的有效rsp的偏移量
 *
 * @return 读取文件成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_read_binary_odo(tT4T_TARGET *target, uint32_t offset, uint16_t max_le, tNCI_BUF **pp_rsp, uint16_t *p_rsp_offset);
/**
 * @brief 写入文件
 *
 * @param[in] target 指令发送的目标
 * @param[in] offset 写入起始偏移位置
 * @param[in] data_len 写入数据长度
 * @param[in] p_dat 写入的数据
 * @param[out] pp_rsp 响应数据
 *
 * @return 写入文件成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_write_binary(tT4T_TARGET *target, uint16_t offset, uint16_t data_len, const uint8_t *p_dat, tNCI_BUF **pp_rsp);

/**
 * @brief 写入文件，Offset Data Object Feature
 *
 * @param[in] target 指令发送的目标
 * @param[in] offset 写入起始偏移位置
 * @param[in] p_dat 写入的数据
 * @param[in] max_lc 最大一条指令写入数据的长度
 * @param[out] pp_rsp 响应数据
 * @param[out] p_data_len 返回真实写入的长度
 *
 * @return 写入文件成功返回NCI_STATUS_OK, 否则返回对应错误码
 */
tNCI_STATUS t4t_write_binary_odo(tT4T_TARGET *target, uint32_t offset, const uint8_t *p_dat, uint16_t max_lc, tNCI_BUF **pp_rsp, uint16_t *p_data_len);

#endif // IS_FEATURE_ON(NCI_FEATURE_RW_T4T) || IS_FEATURE_ON(NCI_FEATURE_T4T_NFCEE)

#endif
